<!--
 * @Description: 外层动态表单，当我写这段代码的时候只有我和神知道这段代码什么意思，过段时间只有神知道这段代码什么意思!
 * @Version: 0.1
 * @Autor: Civet
 * @Date: 2019-11-01 14:53:42
 * @LastEditors: Civet
 * @LastEditTime: 2019-11-07 10:59:54
 -->
<template>
  <el-form
    class="dynamic-form"
    :ref="formConfig.ref"
    :inline="formConfig.inline"
    :model="value"
    :label-position="formConfig.labelPosition"
    :label-width="formConfig.labelWidth"
    :size="formConfig.size"
    :status-icon="formConfig.statusIcon"
  >
    <dynamicFormItem
      v-for="item in formConfig.formItemList"
      :key="item.key"
      :item="item"
      :value="value[item.key]"
      :formItemList="formConfig.formItemList"
      :relationObj="relationObj"
      @input="handleInput($event, item.key, item)"
    ></dynamicFormItem>
  </el-form>
</template>

<script>
import dynamicFormItem from "./baseComponents/baseDynamicForm";
import dynamicFormApi from "@/httpUtils/DynamicForm/apiDynamicForm";

export default {
  components: {
    dynamicFormItem
  },
  name: "dynamicForm",
  watch: {
    // 渲染表单的数据
    formConfig: {
      handler(newValue) {
        // 防抖避免watch监听触发多次
        if (this.formFull !== null) {
          clearTimeout(this.formFull);
        }

        this.formFull = setTimeout(() => {
          // 设置默认值
          const formData = { ...this.value };
          this.formConfig.formItemList.forEach(({ key, value }) => {
            formData[key] = value;
          });
          this.$emit("input", formData);

          // 判断用于联动的对象是否已经存储过值了如果存储过就不再存储
          // if (!Object.keys(this.relationObj).length) {
          this.formConfig.formItemList.forEach(item => {
            this.relationObj[item.key] = item;
          });
          // }
        }, 300);
      },
      deep: true
    },
    // 外层调用v-model的值
    value: {
      handler(newValue) {
        // 防抖避免watch监听触发多次
        if (this.valueFull !== null) {
          clearTimeout(this.valueFull);
        }
        this.valueFull = setTimeout(() => {
          this._backfill(this.formConfig.formItemList, newValue);
        }, 300);
      },
      deep: true
    }
  },
  props: {
    // 渲染表单的数据
    formConfig: {
      type: Object,
      required: true
    },
    // 外层调用v-model的值
    value: {
      type: Object,
      required: true
    }
  },
  filters: {},
  data() {
    return {
      relationObj: {}, // 关联对象,用于做联动
      formFull: null, // 防抖
      valueFull: null // 防抖
    };
  },
  created() {},
  mounted() {},
  methods: {
    /**
     * @description: 表单元素改变的时候触发的事件,用于做联动
     * @param {string} val 触发事件表单元素的值
     * @param {string} key 触发事件表单元素的key
     * @param {object} item 触发事件表单元素的item
     * @return:
     * @author: Civet
     */
    handleInput(val, key, item) {
      if (item.next !== "") {
        this._resetNext(item.next);
        let obj = {};
        obj[key] = val;
        // next
        dynamicFormApi.getDyn(obj).then(res => {
          this.formConfig.formItemList.forEach(formConfigItem => {
            if (item.next === formConfigItem.key) {
              formConfigItem.options = [...res.data];
            }
          });
        });
      }

      // 必须要有的东西，要不就无法获取v-model的值
      this.$emit("input", { ...this.value, [key]: val });
    },
    /**
     * @description: 回填方法（内部方法）
     * @param {array} arr 渲染动态表单的数组
     * @param {object} obj 回填的表单字段
     * @return:
     * @author: Civet
     */
    _backfill(arr, obj) {
      arr.forEach(item => {
        if (obj[item.key]) {
          item.value = obj[item.key];
          return;
        }
        switch (typeof obj[item.key]) {
          case "string":
            item.value = "";
            break;
          case "number":
            item.value = 0;
            break;
          case "boolean":
            item.value = false;
            break;
          case "object":
            if (Array.isArray(obj[item.key])) {
              item.value = [];
            } else {
              item.value = {};
            }
            break;
        }
      });
    },
    /**
     * @description: 联动清除下级
     * @param {object} next 下一级的key
     * @return:
     * @author: Civet
     */
    _resetNext(next) {
      let nextItem = this.relationObj[next];
      let obj = {};
      // 获取下一级的item
      // 判断是不是多选
      if (nextItem.multiple) {
        obj[next] = [];
      } else {
        obj[next] = "";
      }
      this._backfill(this.formConfig.formItemList, obj);

      if (nextItem.next !== "") {
        this._resetNext(nextItem.next);
      }
    }
  },
  destroyed() {}
};
</script>

<style scoped lang="less">
</style>
